﻿/*JQUERY*/
(function ($) {
    var re = /([^&=]+)=?([^&]*)/g;
    var decodeRE = /\+/g;  // Regex for replacing addition symbol with a space
    var decode = function (str) { return decodeURIComponent(str.replace(decodeRE, " ")); };
    $.parseParams = function (query) {
        var params = {}, e;
        while (e = re.exec(query)) {
            var k = decode(e[1]), v = decode(e[2]);
            if (k.substring(k.length - 2) === '[]') {
                k = k.substring(0, k.length - 2);
                (params[k] || (params[k] = [])).push(v);
            }
            else params[k] = v;
        }
        return params;
    };
})(jQuery);


/*APPLICATION*/
function getParams(path) {
    var idx = path.indexOf("?");
    var args = (idx < 0) ? "" : path.substring(idx + 1).toString();;
    return args;
}

function getDate(va) {
    var v, value;
    if ((new Date(va)).toString() == "Invalid Date") {
        v = va.substr(6);
        value = new Date(parseInt(v.substring(0, v.length - 2)));
    }
    else
        value = new Date(va);
    
    var ret = value.getMonth() + 1 + "/" + value.getDate() + "/" + value.getFullYear();
    return ret;
}

function ajax(url, data, callback) {
    var loading = $("#loading");
    $.ajax({
        url: url,
        type: 'POST',
        dataType: 'json',
        data: data,
        contentType: 'application/json;charset=utf-8',
        beforeSend: function () {
            if (loading != null) loading.css({ visibility: 'visible' });
        },
        success: function (result) {
            if (loading != null) loading.css({ visibility: 'hidden' });
            if (callback != null) callback(result);
        },
        error: function (request, status, error) {
            if (loading != null) loading.css({ visibility: 'hidden' });
            alert(request.responseText);
        }
    });
}
function ajaxGet(url, data, callback) {
    var loading = $("#loading");
    loading.css({ visibility: 'visible' });
    $.get(url, data, function (response) {
        callback(response); loading.css({ visibility: 'hidden' });
    });
}

/*SAMMYJS*/
function Routes(routes) {
    var s = Sammy();
    $.each(routes, function (index, item) {
        s.get('#/' + item.path, function () {
            var params = {};
            /*parametros sammy - variables*/
            var valueParamsSammy = this.params[item.variable];
            if (valueParamsSammy) {
                var paramSammy = new Object();
                paramSammy[item.variable] = valueParamsSammy;
                $.extend(params, paramSammy);
            }

            /*parametros externos - query string*/
            var paramsExtra = $.parseParams(getParams(this.path));

            if (item.data) {
                params = $.extend({}, item.data(), paramsExtra);
            }
            else
                params = $.extend({}, params, paramsExtra);

            ajaxGet(item.server, params, function (response) {
                item.call(response);
            });
        });
    });
    return s;
}

/*KNOCKOUT BINDINGHANDLERS */
ko.extenders.addParams = function (target, option) {
    var result = ko.computed({
        read: target,  //always return the original observables value
        write: function (newValue) {
            var current = $.extend(option, newValue);
            target(current);
        }
    });
    result(target());
    return result;
};
ko.bindingHandlers.date = {
    init: function (element, valueAccessor) {
        var jsonDate = valueAccessor();
        element.innerHTML = getDate(jsonDate());
    }
};
ko.bindingHandlers.datepicker = {
    init: function (element, valueAccessor, allBindingsAccessor) {
        //initialize datepicker with some optional options
        var options = allBindingsAccessor().datepickerOptions || {};
        options.autoclose = true;
        $(element).datepicker(options);
        //when a user changes the date, update the view model
        ko.utils.registerEventHandler(element, "changeDate", function (event, ok) {
            var value = valueAccessor();
            if (ko.isObservable(value)) {
                value(event.date);
            }
        });
    },
    update: function (element, valueAccessor) {
        var widget = $(element).data("datepicker");
        //when the view model is updated, update the widget
        if (widget) {
            var currentvalue = ko.utils.unwrapObservable(valueAccessor());
            if (currentvalue) {
                //valida si currentValue es de tipo fecha
                if (currentvalue.getMonth)
                    widget.date = new Date(currentvalue);
                else {
                    widget.date = new Date(getDate(currentvalue));
                    /*empanada*/
                    if (ko.isObservable(valueAccessor())) {
                        var valueChange = valueAccessor();
                        valueChange(widget.date);
                    }
                }
            } else {
                widget.date = currentvalue;
            }
            if (widget.date) {
                widget.setValue();
            }
        }
    }
};
ko.extenders.numeric = function (target, precision) {
    //create a writeable computed observable to intercept writes to our observable
    var result = ko.computed({
        read: target,  //always return the original observables value
        write: function (newValue) {
            var current = target();
            var valueToWrite;
            if (!isNaN(parseFloat(newValue)) && isFinite(newValue)) {
                valueToWrite = newValue;
            }

            //only write if it changed
            if (valueToWrite !== current) {
                target(valueToWrite);
            } else {
                //if the rounded value is the same, but a different value was written, force a notification for the current field
                if (newValue !== current) {
                    target.notifySubscribers(valueToWrite);
                }
            }
        }
    });
    //initialize with current value to make sure it is rounded appropriately
    result(target());
    //return the new computed observable
    return result;
};
ko.observableArray.fn.find = function (prop, data) {
    var valueToMatch = data[prop];
    return ko.utils.arrayFirst(this(), function (item) {
        return item[prop] === valueToMatch;
    });
};
// object should already be observable
var makeChildrenObservables = function (obj, options) {
    // Loop through its children
    if (typeof obj == 'function')
        for (var child in obj()) {
            if (jQuery.inArray(child, options) > -1) {
                if (!ko.isObservable(obj()[child]))
                    obj()[child] = ko.observable(obj()[child]);
            }
        }
};
